/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.area.field;

import java.beans.IntrospectionException;
import nl.cloudfarming.client.area.field.explorer.FieldRootNode;
import java.util.Date;
import java.util.List;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.swing.ActionMap;
import javax.swing.text.DefaultEditorKit;
import nl.cloudfarming.client.area.AreaService;
import nl.cloudfarming.client.model.CommonModelService;
import nl.cloudfarming.client.model.DataProvider;
import nl.cloudfarming.client.model.PartField;
import nl.cloudfarming.client.model.Field;
import nl.cloudfarming.client.model.FieldFile;
import nl.cloudfarming.client.model.FieldPlan;
import nl.cloudfarming.client.model.ProductionUnit;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;

/**
 *
 * @author Timon Veenstra
 */
@ServiceProviders(value = {
    @ServiceProvider(service = DataProvider.class),
    @ServiceProvider(service = AreaService.class),
    @ServiceProvider(service = FieldAreaService.class)
})
public class FieldAreaService extends CommonModelService implements AreaService {
    
    @Override
    final protected String getModuleName() {
        return AreaFieldModule.MODULE_NAME;
    }

    final public List<Field> findAllCurrentFields() {
        startTransaction();
        Query query = getEntityManager().createNamedQuery(Field.Q_FIND_ALL_VALID_FIELDS);
        query.setParameter("date", new Date());
        return query.getResultList();
    }

    @Override
    final public void createNewField(final Field field) {
        persistInTransaction(field);
    }

    @Override
    final public void saveFieldChanges(final Field field) {
        mergeAndPersistInTransaction(field);
    }

    @Override
    final public void createNewFieldFile(final FieldFile fieldFile) {
        persistInTransaction(fieldFile);
    }

    /**
     * Find production units by date
     * @param date The PU should be active on this date 
     * @return The list of PU's active on the specified Date
     */
    public List<ProductionUnit> findProductionUnitsByDate(Date date) {
        startTransaction();
        Query query = getEntityManager().createNamedQuery(ProductionUnit.Q_FIND_ALL_PRODUCTION_UNITS_BY_DATE);
        query.setParameter("date", date);
        return query.getResultList();
    }

    @Override
    final protected void initExplorer() {
        try {
            ExplorerManager manager = new ExplorerManager();
            manager.setRootContext(new FieldRootNode(new FieldLayer("service.explorer.layerlist.field_node.name", this)));
            manager.getRootContext().setDisplayName(NbBundle.getMessage(this.getClass(), "service.explorer.rootnode.displayname"));

            ActionMap map = new ActionMap();
            map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager));
            map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager));
            map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager));
            map.put("delete", ExplorerUtils.actionDelete(manager, true)); // or false

            setExplorerManager(manager, map);
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    /**
     * Find partfields by Date
     * @param date The date the field has to be active.
     * @return The list of partfields active on Date date
     */
    @Override
    public List<PartField> findPartFieldsByDate(Date date) {
        startTransaction();
        Query query = getEntityManager().createNamedQuery(PartField.Q_FIND_ALL_PARTFIELDS_BY_DATE);
        query.setParameter("date", date);
        return query.getResultList();
    }
    
    /**
     * Find a Field by specifying the filename and the checksum
     * @param name Filename
     * @param checksum file checksum
     * @return 
     */
    @Override
    public FieldFile findFieldFileByNameAndChecksum(String name, String checksum) {
        startTransaction();
        Query query = getEntityManager().createNamedQuery(FieldFile.Q_FIND_FIELDFILE_BY_FILENAME_AND_CHECKSUM);
        query.setParameter("fileName", name);
        query.setParameter("checksum", checksum);
        try {
            return (FieldFile) query.getSingleResult();
        } catch (NoResultException ner) {
            return null;
        }
    }
    
    /**
     * Find a Field by ID
     * @param id
     * @return 
     */
    @Override
    public Field findFieldById(long id) {
        startTransaction();
        return getEntityManager().find(Field.class, id);
    }

    
}
